﻿using CatClient;
using CatClient.Context;
using CatClient.Message;
using CatClient.Message.Spi.Internals;
using Newtonsoft.Json;
using PostSharp.Aspects;
using PsCat.Aspet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace PsCat.Aspet
{
    [Serializable]
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public class RequestCatAttribute : CatBaseAttribute
    {
        public override void OnEntry(MethodExecutionArgs args)
        {
            var paramters = args.Method.GetParameters().ToList();
            var urlParam = paramters.FirstOrDefault(x => x.Name == "url");
            if (urlParam != null)
            {
                var url = args.Arguments[paramters.IndexOf(urlParam)].ToString();
                if (!url.StartsWith("http://") && !Regex.IsMatch(url, "^[a-z0-9]+\\://", RegexOptions.IgnoreCase))
                    url = "http://" + url;

                Uri uri = new Uri(url);
                args.MethodExecutionTag = Cat.NewTransaction("PigeonCall", uri.AbsolutePath);
                Cat.LogEvent("PigeonCall.protocol", uri.Scheme);
                Cat.LogEvent("PigeonCall.server", uri.Host, Cat.Success, uri.Query);
                Cat.LogEvent("PigeonCall.port", uri.Port.ToString());
            }

            var contentParam = paramters.FirstOrDefault(x => x.Name == "content");
            if (contentParam != null)
            {
                var content = args.Arguments[paramters.IndexOf(contentParam)].ToString();
                Cat.LogEvent(PureCatConstants.TYPE_URL_BODY, content);
            }

            var headerParam = paramters.FirstOrDefault(x => x.Name == "headers");
            if (headerParam != null)
            {
                var catContext = Cat.LogRemoteCallClient();

                var header = args.Arguments[paramters.IndexOf(headerParam)];
                ((Dictionary<string, string>)header).Add("catContext", JsonConvert.SerializeObject(catContext));
            }
        }

        public override void OnExit(MethodExecutionArgs args)
        {
            if (args.ReturnValue != null)
                Cat.LogEvent(PureCatConstants.TYPE_URL_RESPONSE, string.Empty, PureCatConstants.SUCCESS, JsonConvert.SerializeObject(args.ReturnValue));

            ITransaction transaction = (ITransaction)args.MethodExecutionTag;
            if (transaction == null)
                return;

            transaction.Complete();

            base.OnExit(args);
        }

        public override void OnSuccess(MethodExecutionArgs args)
        {
            ITransaction transaction = (ITransaction)args.MethodExecutionTag;
            if (transaction == null)
                return;

            transaction.Status = PureCatConstants.SUCCESS;

            base.OnSuccess(args);
        }

        public override void OnException(MethodExecutionArgs args)
        {
            base.OnException(args);
        }
    }
}
